home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 2000 July / CD 3 / redhat-6.2.iso / RedHat / instimage / usr / lib / anaconda / lilo.py < prev    next >
Encoding:
Python Source  |  2000-03-08  |  10.6 KB  |  387 lines

  1. import string
  2. import os
  3. import isys
  4. import iutil
  5.  
  6. class LiloConfigFile:
  7.     def __repr__ (self, tab = 0):
  8.     s = ""
  9.     for n in self.order:
  10.         if (tab):
  11.         s = s + '\t'
  12.         if n[0] == '#':
  13.         s = s + n[1:]
  14.         else:
  15.         s = s + n
  16.         if self.items[n]:
  17.             s = s + "=" + self.items[n]
  18.         s = s + '\n'
  19.     for image in self.images:
  20.         (fsType, name, cl) = image
  21.         s = s + "\n%s=%s\n" % (fsType, name)
  22.         s = s + cl.__repr__(1)
  23.     return s
  24.  
  25.     def addEntry(self, item, val = None, replace = 1):
  26.     if not self.items.has_key(item):
  27.         self.order.append(item)
  28.     elif not replace:
  29.         return
  30.  
  31.     if (val):
  32.         self.items[item] = str(val)
  33.     else:
  34.         self.items[item] = None
  35.  
  36.     def getEntry(self, item):
  37.     return self.items[item]
  38.  
  39.     def getImage(self, name):
  40.         for (fsType, label, config) in self.images:
  41.             if label == name:
  42.         return (fsType, config)
  43.     raise IndexError, "unknown image %s" % (name,)
  44.  
  45.     def addImage (self, fsType, name, config):
  46.     self.images.append((fsType, name, config))
  47.  
  48.     def delImage (self, name):
  49.         for entry in self.images:
  50.             fsType, label, config = entry
  51.             if label == name:
  52.                 self.images.remove (entry)
  53.  
  54.     def listImages (self):
  55.     l = []
  56.         for (fsType, label, config) in self.images:
  57.         l.append(label)
  58.     return l
  59.  
  60.     def write(self, file, perms = 0644):
  61.     f = open(file, "w")
  62.     f.write(self.__repr__())
  63.     f.close()
  64.     os.chmod(file, perms)
  65.  
  66.     def read (self, file):
  67.     f = open(file, "r")
  68.     image = None
  69.     for l in f.readlines():
  70.         l = l[:-1]
  71.         orig = l
  72.         while (l and (l[0] == ' ' or l[0] == '\t')):
  73.         l = l[1:]
  74.         if (not l or l[0] == '#'):
  75.         self.order.append('#' + orig)
  76.         continue
  77.         fields = string.split(l, '=', 1)
  78.         if (len(fields) == 2):
  79.         if (fields[0] == "image"):
  80.             image = LiloConfigFile()
  81.             self.addImage(fields[0], fields[1], image)
  82.             args = None
  83.         elif (fields[0] == "other"):
  84.             image = LiloConfigFile()
  85.             self.addImage(fields[0], fields[1], image)
  86.             args = None
  87.                 else:
  88.             args = (fields[0], fields[1])
  89.         else:
  90.         args = (l,)
  91.  
  92.         if (args and image):
  93.         apply(image.addEntry, args)
  94.         elif args:
  95.         apply(self.addEntry, args)
  96.         
  97.     f.close()
  98.  
  99.     def __init__(self):
  100.     self.order = []
  101.     self.images = []        # more (fsType, name, LiloConfigFile) pair
  102.     self.items = {}
  103.  
  104. class LiloConfiguration:
  105.  
  106.     def allowLiloLocationConfig(self, fstab):
  107.     bootDevice = fstab.getBootDevice()
  108.     if bootDevice[0:2] == "md":
  109.         self.setDevice(("raid", bootDevice))
  110.         return None
  111.  
  112.     return 1
  113.  
  114.     def setLiloImages(self, images):
  115.     self.liloImages = images
  116.  
  117.     def getLiloImages(self, fstab):
  118.         (drives, raid) = fstab.raidList()
  119.  
  120.     # rearrange the fstab so it's indexed by device
  121.     mountsByDev = {}
  122.     for (mntpoint, device, fsystem, doFormat, size) in \
  123.             fstab.mountList():
  124.         mountsByDev[device] = mntpoint
  125.  
  126.     for (mntpoint, device, fstype, raidType, start, size, makeup) in raid:
  127.         mountsByDev[device] = mntpoint
  128.         drives.append(device, "", 2, 0, 0)
  129.  
  130.     for (device, mntpoint, fsystem, makeup) in fstab.existingRaidList():
  131.         mountsByDev[device] = mntpoint
  132.         drives.append(device, "", 2, 0, 0)
  133.         
  134.     oldImages = {}
  135.     for dev in self.liloImages.keys():
  136.         oldImages[dev] = self.liloImages[dev]
  137.  
  138.     self.liloImages = {}
  139.         foundDos = 0
  140.     for (dev, devName, fsType, start, size) in drives:
  141.         # ext2 and raid partitions get listed if they're / -- we do
  142.         # not allow non-mounted partitions to be booted anymore as
  143.         # modules are so unlikely to work out as to be not worth
  144.         # worrying about
  145.         #
  146.         # there is a good chance we should configure them as chain
  147.         # loadable, but we don't
  148.  
  149.             # only list dos and ext2 partitions
  150.             if fsType != 1 and fsType != 2:
  151.                 continue
  152.  
  153.         if (mountsByDev.has_key(dev)):
  154.         if mountsByDev[dev] == '/':
  155.             if oldImages.has_key(dev):
  156.             self.liloImages[dev] = oldImages[dev]
  157.             else:
  158.             self.liloImages[dev] = ("linux", 2)
  159.  
  160.             if fsType == 1:
  161.         if foundDos: continue
  162.  
  163.         foundDos = 1
  164.                 isys.makeDevInode(dev, '/tmp/' + dev)
  165.         bootable = isys.checkBoot('/tmp/' + dev)
  166.         os.unlink('/tmp/' + dev)
  167.  
  168.         if bootable:
  169.             if oldImages.has_key(dev):
  170.             self.liloImages[dev] = oldImages[dev]
  171.             else:
  172.             self.liloImages[dev] = ("dos", fsType)
  173.  
  174.     # if there is no default image (self.default is None, or invalid)
  175.     # set the default image to the liunx partition
  176.     if self.default:
  177.         for (label, fsType) in self.liloImages.values():
  178.         if label == self.default: break
  179.         if label != self.default:
  180.         self.default = None
  181.  
  182.     if not self.default:
  183.         for (label, fsType) in self.liloImages.values():
  184.         if fsType == 2:
  185.             self.default = label
  186.             break
  187.  
  188.     return (self.liloImages, self.default)
  189.  
  190.     def makeInitrd (self, kernelTag, instRoot):
  191.     initrd = "/boot/initrd%s.img" % (kernelTag, )
  192.     if not self.initrdsMade.has_key(initrd):
  193.             iutil.execWithRedirect("/sbin/mkinitrd",
  194.                                   [ "/sbin/mkinitrd",
  195.                     "--ifneeded",
  196.                                     initrd,
  197.                                     kernelTag[1:] ],
  198.                                   stdout = None, stderr = None, searchPath = 1,
  199.                                   root = instRoot)
  200.         self.initrdsMade[kernelTag] = 1
  201.     return initrd
  202.  
  203.     def install(self, fstab, instRoot, hdList, upgrade):
  204.     # If self.liloDevice is None, skipping lilo doesn't work
  205.     if not self.liloDevice: return
  206.  
  207.     # If the root partition is on a loopback device, lilo won't work!
  208.     if fstab.rootOnLoop():
  209.         return 
  210.  
  211.     if not self.liloImages:
  212.         (images, default) = self.getLiloImages(fstab)
  213.         self.setLiloImages(images)
  214.  
  215.         # on upgrade read in the lilo config file
  216.     lilo = LiloConfigFile ()
  217.     perms = 0644
  218.         if os.access (instRoot + '/etc/lilo.conf', os.R_OK):
  219.         perms = os.stat(instRoot + '/etc/lilo.conf')[0] & 0777
  220.         #lilo.read (instRoot + '/etc/lilo.conf')
  221.         os.rename(instRoot + '/etc/lilo.conf',
  222.               instRoot + '/etc/lilo.conf.rpmsave')
  223.  
  224.     # Remove any invalid entries that are in the file; we probably
  225.     # just removed those kernels. While we're here, build an index
  226.     # to the already-configured (and valid) lilo images by the lilo
  227.     # label, as we can normally only get them by filename which isn't
  228.     # easily done.
  229.     imagesByLabel = {}
  230.     for image in lilo.listImages():
  231.         (fsType, sl) = lilo.getImage(image)
  232.         if fsType == "other": continue
  233.         if not os.access(instRoot + image, os.R_OK):
  234.         lilo.delImage(image)
  235.         else:
  236.         imagesByLabel[sl.getEntry('label')] = image
  237.  
  238.     bootpart = fstab.getBootDevice()
  239.     boothd = fstab.getMbrDevice()
  240.  
  241.     if (self.liloDevice == "mbr"):
  242.         liloTarget = boothd
  243.     elif (type(self.liloDevice) == type((1,)) and 
  244.           self.liloDevice[0] == "raid"):
  245.         liloTarget = self.liloDevice[1]
  246.     else:
  247.         liloTarget = bootpart
  248.  
  249.     lilo.addEntry("boot", '/dev/' + liloTarget, replace = 0)
  250.     lilo.addEntry("map", "/boot/map", replace = 0)
  251.     lilo.addEntry("install", "/boot/boot.b", replace = 0)
  252.     lilo.addEntry("prompt", replace = 0)
  253.     lilo.addEntry("timeout", "50", replace = 0)
  254.     if self.liloLinear:
  255.         lilo.addEntry("linear", replace = 0)
  256.  
  257.     smpInstalled = (hdList.has_key('kernel-smp') and 
  258.                         hdList['kernel-smp'].selected)
  259.  
  260.     # This is a bit odd, but old versions of Red Hat could install
  261.     # SMP kernels on UP systems, but (properly) configure the UP version.
  262.     # We don't want to undo that, but we do want folks using this install
  263.     # to be able to override the kernel to use during installs. This rule
  264.     # seems to nail this.
  265.     if (upgrade and not isys.smpAvailable()):
  266.         smpInstalled = 0
  267.  
  268.         rootDev = fstab.getRootDevice ()
  269.         if rootDev:
  270.         # strip off the filesystem; we don't need it
  271.             rootDev = rootDev[0]
  272.         else:
  273.             raise RuntimeError, "Installing lilo, but there is no root device"
  274.  
  275.         kernelList = []
  276.         otherList = []
  277.  
  278.         main = self.default
  279.  
  280.         for (drive, (label, liloType)) in self.liloImages.items ():
  281.             if (drive == rootDev) and label:
  282.                 main = label
  283.             elif label:
  284.                 otherList.append (label, "/dev/" + drive)
  285.  
  286.         lilo.addEntry("default", self.default)        
  287.  
  288.     label = main
  289.     if (smpInstalled):
  290.         kernelList.append((main, hdList['kernel-smp'], "smp"))
  291.         label = main + "-up"
  292.  
  293.     kernelList.append((label, hdList['kernel'], ""))
  294.  
  295.     for (label, kernel, tag) in kernelList:
  296.         if imagesByLabel.has_key(label):
  297.         (fsType, sl) = lilo.getImage(imagesByLabel[label])
  298.         lilo.delImage(imagesByLabel[label])
  299.         else:
  300.         sl = LiloConfigFile()
  301.  
  302.         kernelTag = "-%s-%s%s" % (kernel['version'], kernel['release'], tag)
  303.         kernelFile = "/boot/vmlinuz" + kernelTag
  304.  
  305.         initrd = self.makeInitrd (kernelTag, instRoot)
  306.  
  307.         sl.addEntry("label", label)
  308.         if os.access (instRoot + initrd, os.R_OK):
  309.         sl.addEntry("initrd", initrd)
  310.  
  311.         sl.addEntry("read-only")
  312.         sl.addEntry("root", '/dev/' + rootDev)
  313.  
  314.         if self.liloAppend:
  315.         sl.addEntry('append', '"%s"' % (self.liloAppend,))
  316.         
  317.         lilo.addImage ("image", kernelFile, sl)
  318.  
  319.     for (label, device) in otherList:
  320.         try:
  321.         (fsType, sl) = lilo.getImage(device)
  322.         lilo.delImage(device)
  323.         except IndexError:
  324.         sl = LiloConfigFile()
  325.  
  326.         sl.addEntry("label", label)
  327.         lilo.addImage ("other", device, sl)
  328.  
  329.     lilo.write(instRoot + "/etc/lilo.conf", perms = perms)
  330.  
  331.     iutil.execWithRedirect(instRoot + '/sbin/lilo' ,
  332.                    [ "lilo", "-r", instRoot ],
  333.                    stdout = None)
  334.  
  335.     def setDevice(self, device):
  336.     if (type(device) == type((1,))):
  337.         self.liloDevice = device
  338.     elif device != "mbr" and device != "partition" and device:
  339.         raise ValueError, "device must be raid, mbr, partition, or None"
  340.     self.liloDevice = device
  341.  
  342.     def setLinear(self, linear):
  343.     self.liloLinear = linear
  344.  
  345.     def setAppend(self, append):
  346.     self.liloAppend = append
  347.  
  348.     def setDefault(self, default):
  349.     for (label, fsType) in self.liloImages.values():
  350.         if label == default:
  351.         self.default = default
  352.         return
  353.     raise IndexError, "unknown lilo label %s" % (default,)
  354.  
  355.     def getLinear(self):
  356.     return self.liloLinear
  357.  
  358.     def getDevice(self):
  359.     return self.liloDevice
  360.  
  361.     def getAppend(self):
  362.     return self.liloAppend
  363.  
  364.     def __init__(self):
  365.     self.liloImages = {}
  366.     self.liloDevice = 'mbr'
  367.     self.liloLinear = 1
  368.     self.liloAppend = None
  369.     self.default = None
  370.     self.initrdsMade = {}
  371.  
  372.  
  373. if __name__ == "__main__":
  374.     config = LiloConfigFile ()
  375.     config.read ('/etc/lilo.conf')
  376.     print config
  377.     print "image list", config.listImages()
  378.     config.delImage ('/boot/vmlinuz-2.2.5-15')
  379.     print '----------------------------------'
  380.     config = LiloConfigFile ()
  381.     config.read ('/etc/lilo.conf')
  382.     print config
  383.     print '----------------------------------'    
  384.     print config.getImage('/boot/vmlinuz-2.2.5-15')
  385.     
  386.  
  387.